#include <proc.h>
#include <elf.h>
#if defined(__ISA_AM_NATIVE__)
# define EXPECT_TYPE EM_X86_64
#elif defined(__ISA_X86__)
# define EXPECT_TYPE EM_X86_64  // see /usr/include/elf.h to get the right type
#elif defined(__ISA_RISCV64__)
# define EXPECT_TYPE EM_RISCV
#elif defined(__ISA_RISCV32__)
# define EXPECT_TYPE EM_RISCV
#else
# error Unsupported ISA
#endif

#ifdef __LP64__
# define Elf_Ehdr Elf64_Ehdr
# define Elf_Phdr Elf64_Phdr
#else
# define Elf_Ehdr Elf32_Ehdr
# define Elf_Phdr Elf32_Phdr
#endif
extern uint8_t ramdisk_start;
extern uint8_t ramdisk_end;
extern size_t ramdisk_read(void *buf, size_t offset, size_t len);
extern int fs_open(const char *pathname, int flags, int mode);
extern size_t fs_read(int fd, void *buf, size_t len);
extern size_t fs_write(int fd, const void *buf, size_t len);
extern size_t fs_lseek(int fd, size_t offset, int whence);
extern int fs_close(int fd);
static uintptr_t loader(PCB *pcb, const char *filename) {
  int fd = fs_open(filename,0,0);
  Elf64_Ehdr ehdr; /* ELF头 */
  Elf64_Phdr phdr; /* 节头 */
  size_t  seg_num=0;//,shstr_num,str_num;
  fs_read(fd,&ehdr,sizeof(Elf64_Ehdr));
  assert(*(uint64_t*)ehdr.e_ident != 0x464c457f);

  seg_num = ehdr.e_phnum;
  uint64_t base_addr= ehdr.e_phoff;
  uint64_t base_size = ehdr.e_phentsize; 
  for (size_t i = 0; i < seg_num; i++)
  {
    fs_lseek( fd, base_addr+(base_size*i), 0);
    fs_read(fd,&phdr,sizeof(Elf_Phdr)); 
    if (phdr.p_type == PT_LOAD)
    {
      fs_lseek( fd, phdr.p_offset, 0);
      fs_read(fd,(void *)phdr.p_vaddr,phdr.p_filesz);
      memset((void *)(phdr.p_vaddr+phdr.p_filesz),0,phdr.p_memsz-phdr.p_filesz);
    } 
  }
  
  return ehdr.e_entry;
}
void naive_uload(PCB *pcb, const char *filename) {
  uintptr_t entry = loader(pcb, filename);
  Log("Jump to entry = %p", entry);
  ((void(*)())entry)();
}

